fpga驱动oled iic显示代码

您所在的位置:网站首页 i2c verilog时钟产生scl fpga驱动oled iic显示代码

fpga驱动oled iic显示代码

2024-07-15 23:21:43| 来源: 网络整理| 查看: 265

欢迎FPGA工程师加入官方微信技术群

点击蓝字关注我们FPGA之家-中国最好最大的FPGA纯工程师社群

6530509ebd48ee606fb86c3d5c658f13.png

一、 软件平台与硬件平台

  软件平台:

    1、操作系统:Windows-8.1

    2、开发套件:ISE14.7

    3、仿真工具:ModelSim-10.4-SE 、ChipScope

  硬件平台:

    1、 FPGA型号:Xilinx公司的XC6SLX45-2CSG324

    2、 EEPROM型号:Microchip公司的AT24LC04B

二、 原理介绍

  IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线产生于在80年代,最初为音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能状态,如电源和系统风扇。可随时监控内存、硬盘、网络、系统温度等多个参数,增加了系统的安全性,方便了管理。IIC数据传输速率有标准模式(100 kbps)、快速模式(400 kbps)和高速模式(3.4 Mbps),另外一些变种实现了低速模式(10 kbps)和快速+模式(1 Mbps)。

  下图是一个嵌入式系统中处理器仅通过2根线的IIC总线控制多个IIC外设的典型应用图

69061c407b702db921f6c3f14bab039e.png

  图中处理器是IIC主机,它仅仅通过两根信号就可以控制IO扩展器,各种不同的传感器,EEPROM,AD/DAs等设备,这也是IIC总线协议相较于其他协议最有优势的地方。

  IIC总线的特点:

    1、 简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。

    2、 支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控占用IIC总线。

  IIC总线协议详解:

    IIC总线接口是一个标准的双向传输接口,一次数据传输需要主机和从机按照IIC协议的标准进行。I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据,并且在硬件上都需要接一个上拉电阻到VCC。各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址,这样,各控制电路虽然挂在同一条总线上,却彼此独立,互不相关。

  IIC主机往从机里面写入数据的步骤如下:

    1、 主机发送一个起始信号和从机的设备地址给从机

    2、 主机发送数据给从机

    3、 主机发送一个停止信号结束发送过程

  IIC主机从从机里面读出数据的步骤如下:

    1、 主机发送一个起始信号和从机的设备地址给从机

    2、 主机发送一个要读取的地址给从机

    3、 主机从从机接收数据

    4、 主机发送一个停止信号给从机结束整个接收过程

  总的来说,IIC总线在通信的过程中一共有一下几种状态:

  1、空闲状态

  IIC 总线的 SDA 和 SCL 两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

  2、起始状态和结束状态

  在时钟线 SCL 保持高电平期间,数据线 SDA 上的电平被拉低(即负跳变),定义为 I2C 总线总线的起始信号,它标志着一次数据传输的开始。起始信号是由主控器主动建立的,在建立该信号之前 I2C 总线必须处于空闲状态。

  在时钟线 SCL 保持高电平期间,数据线 SDA 被释放,使得 SDA 返回高电平(即正跳变),称为 I2C 总线的停止信号,它标志着一次数据传输的终止。停止信号也是由主控器主动建立的,建立该信号之后,I2C 总线将返回空闲状态。

  起始信号和结束信号如下图所示

ed885bf693a782c012f7ac962056ef43.png

  3、有效的数据位传输

  在 IIC 总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在 SCL 串行时钟的配合下,数据在 SDA 上从高位向低位依次串行传送每一位的数据。进行数据传送时,在 SCL 呈现高电平期间,SDA 上的电平必须保持稳定,低电平为数据 0,高电平为数据 1。只有在 SCL 为低电平期间,才允许 SDA 上的电平改变状态。下图是0xaa在IIC总线上有效传输(有效传输是指第9个时钟的高电平期间,从机给主机反馈了一个有效的应答位0)的图示

bc42688466dc6a3f8d088db0401fa8f6.png

  4、应答信号与非应答信号

    I2C 总线上的所有数据都是以 8 位字节传送的,发送器(主机)每发送一个字节,就在第9个时钟脉冲期间释放数据线,由接收器(从机)反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。对于反馈有效应答位 ACK 的要求是,接收器在第 9 个时钟脉冲之前的低电平期间将 SDA 线拉低,并且确保在该时钟的高电平期间为稳定的低电平。

    对非应答位(NACK)还要特别说明的是,还有以下四种情况IIC通信过程中会产生非应答位:

      1、接收器(从机)正在处理某些实时的操作无法与主机实现IIC通信的时候,接收器(从机)会给主机反馈一个非应答位(NACK)

      2、主机发送数据的过程中,从机无法解析发送的数据,接收器(从机)也会给主机反馈一个非应答位(NACK)

      3、主机发送数据的过程中,从机无法再继续接收数据,接收器(从机)也会给主机反馈一个非应答位(NACK)

      4、主机从从机中读取数据的过程中,主机不想再接收数据,主机会给从机反馈一个非应答位(NACK),注意,这种情况是主机给从机反馈一个非应答位(NACK)

  关于有效应答位的图示在上一传输0xaa的图中可以清楚的看到,关于非应答位的图示见下图

6678027257ebc1909a2d24a02471b32b.png

  了解清楚IIC总线在通信的过程中的几种状态以后接下来就具体看看IIC总线的读写过程吧。

  1、主机通过IIC总线往从机里面写数据

    主机通过IIC总线往从机中写数据的时候,主机首先会发送一个起始信号,接着把IIC从机的7位设备地址后面添一个0(设备地址后面的0表示主机向从机写数据,1表示主机从从机中读数据)组成一个8位的数据,把这个8位的数据发给从机,发完这8位的数据以后主机马上释放SDA信号线等待从机的应答,如果从机正确收到这个数据,从机就会发送一个有效应答位0给主机告诉主机自己已经收到了数据,主机收到从机的有效应答位以后 ,接下来主机会发送想要写入的寄存器地址,寄存器发送完毕以后主机同样会释放SDA信号线等待从机的应答,从机如果正确收到了主机发过来的寄存器地址,从机会再次发送一个有效应答位给主机,主机收到从机的有效应答位0以后,接下来主机就会给从机发送想要写入从机的数据,从机正确收到这个数据以后仍然像之前两次一样会给主机发送一个有效应答位,主机收到这个有效应答位以后给从机发送一个停止信号,整个传输过程就结束了。下图是整个传输过程的示意图:

a2f89170bb50acc845b09a71712cf184.png

  特别注意:上图中灰色的地方表示主机正在控制SDA信号线,白色的地方表示从机正在控制SDA信号线。

  2、主机通过IIC总线从从机里面读数据

    主机通过IIC总线从从机中读数据的过程与写数据的过程有相似之处,但是读数据的过程还多了一些额外的步骤。主机从从机读数据时主机首先会发送一个起始信号,接着把IIC从机的7位设备地址后面添一个0(设备地址后面的0表示主机向从机写数据,1表示主机从从机中读数据),把这个8位的数据发给从机,发完这8位的数据以后主机马上释放SDA信号线等待从机的应答,如果从机正确收到这个数据,从机就会发送一个有效应答位0给主机告诉主机自己已经收到了数据,主机收到从机的有效应答位以后 ,接下来主机会发送想要读的寄存器地址,寄存器发送完毕以后主机同样会释放SDA信号线等待从机的应答,从机如果正确收到了主机发过来的寄存器地址,从机会再次发送一个有效应答位给主机,主机收到从机的有效应答位0以后,主机会给从机再次发送一次起始信号,接着把IIC从机的7位设备地址后面添一个1(设备地址后面的0表示主机向从机写数据,1表示主机从从机中读数据),注意,第一次是在设备地址后面添0,这一次是在设备地址后面添1,把这个8位的数据发给从机,发完这8位的数据以后主机马上释放SDA信号线等待从机的应答,如果从机正确收到这个数据,从机就会发送一个有效应答位0给主机告诉主机自己已经收到了数据,接着从机继续占用SDA信号线给主机发送寄存器中的数据,发送完毕以后,主机再次占用SDA信号线发送一个非应答信号1给从机,主机发送一个停止信号给从机结束整个读数据的过程。下图是整个读数据过程的示意图

cf626b76ddd310044e102b6a2b649831.png

  特别注意:上图中灰色的地方表示主机正在控制SDA信号线,白色的地方表示从机正在控制SDA信号线。

三、 目标任务

  1、编写IIC总线主机给从机发送数据的代码,实现FPGA(主机)往EEPROM(从机)的0x23这个地址写入0x45这个数据

  2、编写IIC总线主机从从机接收数据的代码,实现FPGA(主机)从EEPROM(从机)的0x23这个地址读出0x45这个数据,并用0x45这个数据的低四位驱动4个LED

四、 设计思路与Verilog代码编写

4.1、 IIC发送模块的接口定义与整体设计

  Verilog编写的IIC发送模块除了进行IIC通信的两根信号线(SCL和SDA)以外还要包括一些时钟、复位、使能、并行的输入输出以及完成标志位。其框图如下所示

68ccfa0c8e5c77d8e2b77bce91addd8d.png

  其中:

  I_clk是系统时钟;

  I_rst_n是系统复位;

  I_iic_send_en发送使能信号,当I_iic_send_en为1时IIC主机(FPGA)才能给IIC从机发送数据;

  I_dev_addr[6:0]是IIC从机的设备地址;

  I_word_addr[7:0]是字地址,也就是我们想要操作的IIC设备的内部存储地址;

  I_write_data[7:0]是主机(FPGA)要往IIC字地址中写入的数据;

  O_done_flag是主机(FPGA)发送一个字节完成标志位,发送完成后会产生一个高脉冲;

  O_scl是IIC总线的串行时钟线;

  IO_sda是IIC总线的串行数据线;

  要想实现iic_send模块的功能,还是先得抽象出发送一个字节数据时序的状态机,这里把24LC04B发送过程的时序贴一遍

66a6f480a0aafa54bda301586da716e5.png

  注意,上图中的控制字节(CONTROL BYTE)实际上就是代码里面定义的7-bit设备物理地址与最后1-bit的读写控制位拼接组成的。

  通过观察上面的时序图可以看出,发送一个字节的数据之前必须要先发送起始位,然后发送控制字节,接着等待应答,然后在发送字地址,接着在等待应答。数据发送完毕以后,在等待最后一个应答,应答成功后发送停止信号结束整个过程。所以,根据这个流程,可以归纳出如下几个状态:

  状态0:空闲状态,用来初始化各个寄存器的值

  状态1:加载IIC设备的物理地址

  状态2:加载IIC设备的字地址

  状态3:加载要发送的数据

  状态4:发送起始信号

  状态5:发送一个字节,从高位开始发送

  状态6:接收应答状态的应答位

  状态7:校验应答位

  状态8:发送停止信号

  状态9:IIC写操作结束

  需要注意的是上面的各个状态并不是按照顺序执行的,有些状态要复用多次,比如状态5发送字节的状态就需要复用三次用来发送三个8-bit的数据;同样,状态6和状态7也要复用多次。

  抽象出状态机以后,写代码之前先分析一下代码中要注意的一些关键点:

  1、由于IIC时序要求数据线SDA在串行时钟线的高电平保持不变,在串行时钟线的低电平才能变化,所以代码里面必须在串行时钟线低电平的正中间产生一个标志位,写代码的时候在这个标志位处改变SDA的值,这样就可以保证SDA在SCL的高电平期间保持稳定了。同理,由于IIC从机(24LC04)在接收到主机(FPGA)发送的有效数据以后会在SCL高电平期间产生一个有效应答信号0,所以为了保证采到的应答信号准确,必须在SCL高电平期间的正中间判断应答信号是否满足条件(0为有效应答,1为无效应答),因此代码里面还必须在串行时钟线高电平的正中间产生一个标志位,在这个标志下接收应答位并进行校验。

  这部分的代码通过一个计数器就很容易实现,代码如下:

616f859ed9391f9ba497f657abcc93b2.png

parameter C_DIV_SELECT = 10'd500 ; // 分频系数选择parameter C_DIV_SELECT0 = (C_DIV_SELECT >> 2) - 1 , // 用来产生IIC总线SCL低电平最中间的标志位 C_DIV_SELECT1 = (C_DIV_SELECT >> 1) - 1 , C_DIV_SELECT2 = (C_DIV_SELECT0 + C_DIV_SELECT1) + 1 , // 用来产生IIC总线SCL高电平最中间的标志位 C_DIV_SELECT3 = (C_DIV_SELECT >> 1) + 1 ; // 用来产生IIC总线SCL下降沿标志位always @(posedge I_clk or negedge I_rst_n)beginif(!I_rst_n) R_scl_cnt 发送8-bit数据->接收应答位->校验应答位->加载第二个8-bit数据……....。所以为了复用中间标红的这几个状态,必须在加载8-bit数据这个状态提前设置好校验应答位状态执行完毕以后的后一个状态的位置,这在代码里面通过R_jump_state这个变量来完成。这一点也必须对照着代码来进行理解。

  思路理清楚以后就可以直接编写Verilog代码了,iic_send模块的代码如下:

616f859ed9391f9ba497f657abcc93b2.png

module iic_send(input I_clk , // 系统50MHz时钟input I_rst_n , // 系统全局复位input I_iic_send_en , // IIC发送使能位input [6:0] I_dev_addr , // IIC设备的物理地址input [7:0] I_word_addr , // IIC设备的字地址,即我们想操作的IIC的内部地址input [7:0] I_write_data , // 往IIC设备的字地址写入的数据output reg O_done_flag , // 读或写IIC设备结束标志位// 标准的IIC设备总线output O_scl , // IIC总线的串行时钟线inout IO_sda // IIC总线的双向数据线);parameter C_DIV_SELECT = 10'd500 ; // 分频系数选择parameter C_DIV_SELECT0 = (C_DIV_SELECT >> 2) - 1 , // 用来产生IIC总线SCL低电平最中间的标志位 C_DIV_SELECT1 = (C_DIV_SELECT >> 1) - 1 , C_DIV_SELECT2 = (C_DIV_SELECT0 + C_DIV_SELECT1) + 1 , // 用来产生IIC总线SCL高电平最中间的标志位 C_DIV_SELECT3 = (C_DIV_SELECT >> 1) + 1 ; // 用来产生IIC总线SCL下降沿标志位reg [9:0] R_scl_cnt ; // 用来产生IIC总线SCL时钟线的计数器reg R_scl_en ; // IIC总线SCL时钟线使能信号reg [3:0] R_state ;reg R_sda_mode ; // 设置SDA模式,1位输出,0为输入reg R_sda_reg ; // SDA寄存器reg [7:0] R_load_data ; // 发送/接收过程中加载的数据,比如设备物理地址,字地址和数据等reg [3:0] R_bit_cnt ; // 发送字节状态中bit个数计数reg R_ack_flag ; // 应答标志reg [3:0] R_jump_state ; // 跳转状态,传输一个字节成功并应答以后通过这个变量跳转到导入下一个数据的状态wire W_scl_low_mid ; // SCL的低电平中间标志位wire W_scl_high_mid ; // SCL的高电平中间标志位wire W_scl_neg ; // SCL的下降沿标志位assign IO_sda = (R_sda_mode == 1'b1) ? R_sda_reg : 1'bz ;always @(posedge I_clk or negedge I_rst_n)beginif(!I_rst_n) R_scl_cnt > 2) - 1 , // 用来产生IIC总线SCL低电平最中间的标志位 C_DIV_SELECT1 = (C_DIV_SELECT >> 1) - 1 , // 用来产生IIC串行时钟线 C_DIV_SELECT2 = (C_DIV_SELECT0 + C_DIV_SELECT1) + 1 , // 用来产生IIC总线SCL高电平最中间的标志位 C_DIV_SELECT3 = (C_DIV_SELECT >> 1) + 1 ; // 用来产生IIC总线SCL下降沿标志位reg [9:0] R_scl_cnt ; // 用来产生IIC总线SCL时钟线的计数器reg R_scl_en ; // IIC总线SCL时钟线使能信号reg [3:0] R_state ;reg R_sda_mode ; // 设置SDA模式,1位输出,0为输入reg R_sda_reg ; // SDA寄存器reg [7:0] R_load_data ; // 发送/接收过程中加载的数据,比如设备物理地址,字地址和数据等reg [3:0] R_bit_cnt ; // 发送字节状态中bit个数计数reg R_ack_flag ; // 应答标志reg [3:0] R_jump_state ; // 跳转状态,传输一个字节成功并应答以后通过这个变量跳转到导入下一个数据的状态reg [7:0] R_read_data_reg ;wire W_scl_low_mid ; // SCL的低电平中间标志位wire W_scl_high_mid ; // SCL的高电平中间标志位assign IO_sda = (R_sda_mode == 1'b1) ? R_sda_reg : 1'bz ;always @(posedge I_clk or negedge I_rst_n)beginif(!I_rst_n) R_scl_cnt


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭